package com.sfexpress.tools;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;

import com.google.common.base.Function;
import com.google.common.collect.Maps;
import com.sfexpress.tools.entity.ConsCheckResult;
import com.sfexpress.tools.entity.MysqlTableInfo;
import com.sfexpress.tools.entity.MysqlTableConstInfo;
import com.sfexpress.tools.entity.ConsCheckResult.ItemResult;
import com.sfexpress.tools.entity.ConsCheckResult.ConflictItem;
import com.sfexpress.tools.utils.Pair;
import com.sfexpress.tools.utils.SetUtil;

/**
 * 
 * mysql表级约束一致性检查类
 * 
 * @author CrazyPig
 *
 */
public class MysqlTableConstChecker extends AbstractChecker {
	
	public void checkConsistency(MysqlTableInfo pvTableInfo, MysqlTableInfo gvTableInfo, ConsCheckResult result) {
		
		logger.info("开始执行表约束一致性校验 ...");
		
		Map<String, MysqlTableConstInfo> pvTbLevelConstMap = getTbLevelConstMap(pvTableInfo.getTbLevelConstInfoList());
		Map<String, MysqlTableConstInfo> gvTbLevelConstMap = getTbLevelConstMap(gvTableInfo.getTbLevelConstInfoList());
	
		Set<String> pvTbLevelConstSet = pvTbLevelConstMap.keySet();
		Set<String> gvTbLevelConstSet = gvTbLevelConstMap.keySet();
		
		Set<String> newItems = SetUtil.getDiffSet(gvTbLevelConstSet, pvTbLevelConstSet);
		Set<String> deletedItems = SetUtil.getDiffSet(pvTbLevelConstSet, gvTbLevelConstSet);
		
		if(newItems.size() > 0) {
//			result.setCoincident(false);
			logger.warn("检测到灰度版本表存在新的表约束 : " + Arrays.toString(newItems.toArray()));
			result.getTbConstCheckResult().setCoincident(false);
			for(String newItem : newItems) {
				result.getTbConstCheckResult().getNewItems().add(gvTbLevelConstMap.get(newItem));
			}
		}
		
		if(deletedItems.size() > 0) {
//			result.setCoincident(false);
			logger.warn("检测到灰度版本没有的表约束 : " + Arrays.toString(deletedItems.toArray()));
			result.getTbConstCheckResult().setCoincident(false);
			for(String delItem : deletedItems) {
				result.getTbConstCheckResult().getDeletedItems().add(pvTbLevelConstMap.get(delItem));
			}
		}
		
		Set<String> commItems = SetUtil.getInterSet(pvTbLevelConstSet, gvTbLevelConstSet);
		
		for(String item : commItems) {
			MysqlTableConstInfo pvItem = pvTbLevelConstMap.get(item);
			MysqlTableConstInfo gvItem = gvTbLevelConstMap.get(item);
			if(!checkConsistency(pvItem, gvItem, result)) {
//				result.setCoincident(false);
				logger.warn("检测到有不一致的表约束 : " );
				logger.warn("From 生产版本库 : " + pvItem);
				logger.warn("From 灰度版本库 : " + gvItem);
				result.getTbConstCheckResult().setCoincident(false);
				result.getTbConstCheckResult().getConflictItems().add(new Pair<MysqlTableConstInfo, MysqlTableConstInfo>(pvItem, gvItem));
			}
		}
		
		logger.info("表约束一致性校验结束!");
		
	}
	
	private boolean checkConsistency(MysqlTableConstInfo pvTbLevelConstInfo, MysqlTableConstInfo gvTbLevelConstInfo, ConsCheckResult result) {
		
//		if(!StringUtils.equals(pvTbLevelConstInfo.getConstraintName(), gvTbLevelConstInfo.getConstraintName())) {
//			return false;
//		}
		ItemResult<MysqlTableConstInfo> tbConstInfoCheckResult = result.getTbConstCheckResult();
		String key = pvTbLevelConstInfo.getConstraintName();
		boolean flag = true;
		if(!StringUtils.equals(pvTbLevelConstInfo.getConstraintType(), gvTbLevelConstInfo.getConstraintType())) {
			flag = false;
			tbConstInfoCheckResult.addConflictItem(key, new ConflictItem(key, "CONST_TYPE", pvTbLevelConstInfo.getConstraintType(), gvTbLevelConstInfo.getConstraintType()));
		}
		
		return flag;
	}
	
	private Map<String, MysqlTableConstInfo> getTbLevelConstMap(List<MysqlTableConstInfo> tbLevelConstInfoList) {
		
		return Maps.uniqueIndex(tbLevelConstInfoList, new Function<MysqlTableConstInfo, String>() {

			@Override
			public String apply(MysqlTableConstInfo item) {
				return item.getConstraintName();
			}
		});
		
	}

}
